package com.teamclub.erp.sservices

import java.io.File
import java.util
import java.util.{Date, HashMap, List, Map}

import io.ebean.{Ebean, ExpressionList}
import com.google.common.collect.{Lists, Maps}
import com.teamclub.domain.erp.dealer.DealerInfoLink
import com.teamclub.domain.erp.product.ProductSpecs
import com.teamclub.domain.erp.storage.{StorageRecord, StorageRecordDetail}
import com.teamclub.domain.system.AppOrgArch
import com.teamclub.erp.sforms.StorageRecordForm
import com.teamclub.util.errors.ErrorCode
import com.teamclub.util.files.{ExcelExporter, ExcelImporter}
import com.teamclub.util.libs.{F, Libs}
import com.teamclub.util.page.Pager
import org.apache.commons.lang3.StringUtils
import org.slf4j.LoggerFactory
import org.springframework.beans.BeanUtils
import org.springframework.stereotype.Service

import scala.collection.JavaConversions._

/**
  * Created by ilkkzm on 17-9-11.
  */
@Service
class StorageRecordService {
  val logger = LoggerFactory.getLogger(classOf[StorageRecordService])

  def expr(where: ExpressionList[StorageRecord], form: StorageRecordForm): Unit = {
    if(form.id != null) {
      where.eq("id", form.id)
    }
    if(form.recordType != null) {
      where.eq("recordType", form.recordType)
    }
    if(form.dealerOrganNo != null) {
      where.eq("dealerOrganNo", form.dealerOrganNo)
    }
    if(form.producerOrganNo != null) {
      where.eq("producerOrganNo", form.producerOrganNo)
    }
    if(form.actionStartTime != null) {
      where.ge("actionTime", Libs.firstOfDate(form.actionStartTime))
    }
    if(form.actionEndTime != null) {
      where.le("actionTime", Libs.endOfDate(form.actionEndTime))
    }
    if(StringUtils.isNotBlank(form.linkCustomer)) {
      where.like("linkCustomer", form.linkCustomer + "%")
    }
    if(StringUtils.isNotBlank(form.batchNo)) {
      where.eq("batchNo", form.batchNo)
    }
    if(form.operatorId != null) {
      where.eq("operatorId", form.operatorId)
    }
    where.orderBy("actionTime desc")
  }

  def exprDetail(where: ExpressionList[StorageRecordDetail], form: StorageRecordForm): Unit = {
    if(form.recordType != null) {
      where.eq("recordType", form.recordType)
    }
    if(form.dealerOrganNo != null) {
      where.eq("dealerOrganNo", form.dealerOrganNo)
    }
    if(form.producerOrganNo != null) {
      where.eq("producerOrganNo", form.producerOrganNo)
    }
    if(StringUtils.isNotBlank(form.erCode)) {
      where.eq("erCode", form.erCode)
    }
    if(StringUtils.isNotBlank(form.batchNo)) {
      where.eq("batchNo", form.batchNo)
    }
    if(form.operatorId != null) {
      where.eq("operatorId", form.operatorId)
    }
  }

  def list(form: StorageRecordForm): F.Either[Pager[StorageRecord], ErrorCode] = {
    val where = Ebean.find(classOf[StorageRecord]).where()
    expr(where, form)
    F.Either.Left(Pager.genePager(where.query(), form))
  }

  def detailList(form: StorageRecordForm): F.Either[Pager[StorageRecordDetail], ErrorCode] = {
//    if(StringUtils.isBlank(form.getBatchNo)) {
//      return F.Either.Right(ErrorCode.ref("BatchNo 未传递"))
//    }
//    if(form.operatorId == null) {
//      return F.Either.Right(ErrorCode.ref("operatorId 未传递"))
//    }
    val where = Ebean.find(classOf[StorageRecordDetail]).where()
    exprDetail(where, form)
    val pager: Pager[StorageRecordDetail] = Pager.genePager(where.query(), form)
    val data = pager.data
    for(single: StorageRecordDetail <- data) {
      if (StringUtils.isBlank(single.getErCode) || single.getErCode.length < 20)  { }
      else {
        val code = single.getErCode.substring(0, 5)
        val productSpecs = Ebean.find(classOf[ProductSpecs]).where.eq("specsCode", code).eq("organNo", single.getProducerOrganNo).findOne
        if(productSpecs != null) {
          single.setErCodeSpec(productSpecs.getSpecsNum + "/" + productSpecs.getSpecsUnit)
          single.setErCodeName(productSpecs.getSpecsName)
        }
        val storageRecord = Ebean.find(classOf[StorageRecord]).where().eq("batchNo", single.getBatchNo).eq("dealerOrganNo", single.getDealerOrganNo).setMaxRows(1).findOne();
        if(storageRecord != null) {
          single.setFormattedActionTime(storageRecord.getFormattedActionTime)
          single.setLinkCustomer(storageRecord.getLinkCustomer)
        }
      }
    }
    F.Either.Left(pager)
  }

  def add(form: StorageRecordForm): F.Either[Boolean, ErrorCode] = {
    val batchNo = System.currentTimeMillis().toString //批次id
    form.setBatchNo(batchNo)

    val trans = Ebean.beginTransaction()
    try {
      //保存主记录
      val instance = new StorageRecord
      BeanUtils.copyProperties(form, instance)
      instance.setCreateTime(new Date())
      instance.save()
      //保存明细记录
      val lists: List[StorageRecordDetail] = Lists.newArrayList()
      if(StringUtils.isNotBlank(form.erCodes)) {
        val erCodes = form.erCodes.split(",")
        for(erCode: String <- erCodes; if(StringUtils.isNotBlank(erCode))) {
          val instance = new StorageRecordDetail
          form.setErCode(erCode)
          BeanUtils.copyProperties(form, instance)
          lists.add(instance)
        }
      }
      if(StringUtils.isNotBlank(form.batchErCodes)) {
        val batchErCodes = form.batchErCodes.split(",")
        for(batchErCode: String <- batchErCodes) {
          val idx = batchErCode.indexOf("@")
          val firstErCode = batchErCode.substring(0, idx)
          val count = batchErCode.substring(idx + 1).toInt
          val firstFrontErCode = firstErCode.substring(0, firstErCode.length - 6)
          val firstBackErCode = firstErCode.substring(firstErCode.length - 6)
          for(i <- 0 until count) {
            val erCode = firstFrontErCode + ("%06d".format(firstBackErCode.toInt + i))
            val instance = new StorageRecordDetail
            form.setErCode(erCode)
            BeanUtils.copyProperties(form, instance)
            lists.add(instance)
          }
        }
      }
      Ebean.saveAll(lists)
      trans.commit()
    } catch {
      case e: Exception => {
        logger.error("", e)
        trans.rollback()
        return F.Either.Right(ErrorCode.BIZ_FAILURE)
      }
    } finally {
      trans.end()
    }
    F.Either.Left(true)
  }

  def upload(file: File): F.Either[Boolean, ErrorCode] = {
    val importer = new ExcelImporter(file)
    importer.readValues(new F.Function[List[String], String] {
      override def apply(datas: util.List[String]): String = {
        for(data: String <- datas) {
          println(data)
        }
        return "";
      }
    })
    F.Either.Left(true)
  }

  def download(form: StorageRecordForm):F.Either[File, ErrorCode] = {
    var titles: List[String] = null
    var keys: List[String] = null
    if(form.recordType  == 1) {
      titles = Lists.newArrayList("进货日期", "仓库", "品名", "批号", "箱号")
      keys = Lists.newArrayList("formattedActionTime", "storageName", "erCodeName", "erBatchData", "erMaterialBox")
    } else if(form.recordType == 2){
      titles = Lists.newArrayList("销售日期", "客户名称", "仓库", "单号", "品名", "批号", "箱号")
      keys = Lists.newArrayList("formattedActionTime","linkCustomer","storageName","linkOrderNo", "erCodeName", "erBatchData", "erMaterialBox")
    } else {
      logger.warn("form recordType 只能为1或者2")
      F.Either.Right(ErrorCode.BIZ_FAILURE)
    }

    val contents = downloadRecordList(form)
    val instance = new ExcelExporter(
      form.fileName,
      "Sheet1",
      titles,
      keys,
      contents)
    val file = instance.downLoad
    F.Either.Left(file)
  }

  def downloadRecordList(form: StorageRecordForm): List[Map[String, Object]] = {
    val where = Ebean.find(classOf[StorageRecord]).where()
    expr(where, form)
    val dealerInfo = Ebean.find(classOf[DealerInfoLink]).where().eq("dealerOrganNo", form.dealerOrganNo).setMaxRows(1).findOne()
    val belongOrganNo = if(dealerInfo == null) form.getProducerOrganNo else ""
    val datas: List[StorageRecord] = where.findList()
    val respDatas: List[Map[String, Object]] = Lists.newArrayList()
    for(single: StorageRecord <- datas) {
      val detailList = Ebean.find(classOf[StorageRecordDetail]).where().eq("dealerOrganNo", form.dealerOrganNo).eq("batchNo", single.getBatchNo).findList()
      for(detail: StorageRecordDetail <- detailList) {
        if (StringUtils.isBlank(detail.getErCode) || detail.getErCode.length < 20) { }
        else {
          val code = detail.getErCode.substring(0, 5)
          val productSpecs = Ebean.find(classOf[ProductSpecs]).where.eq("specsCode", code).eq("organNo", belongOrganNo).findOne
          if(productSpecs != null) {
            detail.setErCodeSpec(productSpecs.getSpecsNum + "/" + productSpecs.getSpecsUnit)
            detail.setErCodeName(productSpecs.getSpecsName)
          }
        }
        val respSingle = new HashMap[String, Object]
        respSingle.put("formattedActionTime", single.getFormattedActionTime)
        respSingle.put("linkCustomer", single.getLinkCustomer)
        respSingle.put("storageName", single.getStorageName)
        respSingle.put("linkOrderNo", single.getLinkOrderNo)
        respSingle.put("erCodeName", detail.getErCodeName)
        respSingle.put("erBatchData", detail.getErBatchData)
        respSingle.put("erMaterialBox", detail.getErMaterialBox)
        respDatas.add(respSingle)
      }
    }
    respDatas
  }

}
